import unittest
from fractions import Fraction as F

from abcesac.music import *

class KeyTestCase(unittest.TestCase):

    def test_get_notes(self):
        got = Key('C').get_notes()
        want = ['C','D','E','F','G','A','B']
        self.assertEquals(got, want)

        got = Key('D').get_notes()
        want = ['D','E','F#','G','A','B','C#']
        self.assertEquals(got, want)

        got = Key('E').get_notes()
        want = ['E','F#','G#','A','B','C#','D#']
        self.assertEquals(got, want)

        got = Key('Eb').get_notes()
        want = ['Eb','F','G','Ab','Bb','C','D']
        self.assertEquals(got, want)

    def test_interval(self):
        got = Key('C').interval('C', 5)
        self.assertEquals(got, 'A')

        got = Key('C').interval('B', 5)
        self.assertEquals(got, 'G')

        got = Key('C').interval('B', 6)
        self.assertEquals(got, 'A')

        got = Key('G#').interval('B', 6)
        self.assertEquals(got, 'A#')

    def test_length_value(self):
        got = length_value(F(1,8))
        self.assertEquals(got, (F(1,8),0))

        got = length_value(F(2,8))
        self.assertEquals(got, (F(1,4),0))

        got = length_value(F(3,8))
        self.assertEquals(got, (F(1,4),1))

        got = length_value(F(4,8))
        self.assertEquals(got, (F(1,2),0))

        got = length_value(F(5,8))
        self.assertEquals(got, (F(1,2),1))

        got = length_value(F(6,8))
        self.assertEquals(got, (F(1,2),1))

        got = length_value(F(7,8))
        self.assertEquals(got, (F(1,2),2))

        got = length_value(F(8,8))
        self.assertEquals(got, (F(1,1),0))

        got = length_value(F(9,8))
        self.assertEquals(got, (F(1,1),1))

        got = length_value(F(10,8))
        self.assertEquals(got, (F(1,1),1))

        got = length_value(F(16,8))
        self.assertEquals(got, (F(2,1),0))

    def test_tuplets(self):
        tuplet = Tuplet(3, 2)
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        self.assertEquals(tuplet.length, F(2,8))

        tuplet = Tuplet(3, 2)
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        self.assertEquals(tuplet.length, F(2,8))

        tuplet = Tuplet(5, 3)
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,8)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        self.assertEquals(tuplet.length, F(3,8))

        tuplet = Tuplet(7, 3)
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        tuplet.add_note(Note(name='C', length=F(1,16)))
        self.assertEquals(tuplet.length, F(3,16))

    def test_modes(self):
        got = Key('C').mode_scale('major')
        want = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('ionian')
        want = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('minor')
        want = ['C', 'D', 'Eb', 'F', 'G', 'Ab', 'Bb']
        self.assertEquals(got, want)

        got = Key('E').mode_scale('minor')
        want = ['E', 'F#', 'G', 'A', 'B', 'C', 'D']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('dorian')
        want = ['C', 'D', 'Eb', 'F', 'G', 'A', 'Bb']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('phrygian')
        want = ['C', 'Db', 'Eb', 'F', 'G', 'Ab', 'Bb']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('lydian')
        want = ['C', 'D', 'E', 'F#', 'G', 'A', 'B'] 
        self.assertEquals(got, want)

        got = Key('C').mode_scale('mixolydian')
        want = ['C', 'D', 'E', 'F', 'G', 'A', 'Bb']
        self.assertEquals(got, want)

        got = Key('C').mode_scale('aeolian')
        want = ['C', 'D', 'Eb', 'F', 'G', 'Ab', 'Bb'] 
        self.assertEquals(got, want)

        got = Key('C').mode_scale('locrian')
        want = ['C', 'Db', 'Eb', 'F', 'Gb', 'Ab', 'Bb']
        self.assertEquals(got, want)

        got = Key('D').mode_scale('major')
        want = ['D', 'E', 'F#', 'G', 'A', 'B', 'C#']
        self.assertEquals(got, want)
        

if __name__ == '__main__':
    unittest.main()
